/*
 * Copyright 2005 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package core.api.a2;

import api.kiecontainer.FactHandle;
import core.api.a4.InternalDataSource;
import core.api.a4.LeftTuple;
import core.api.a4.RightTuple;
import core.impl.p1.EqualityKey;
import core.impl.p1.RuleBasePartitionId;
import core.impl.p3.TraitTypeEnum;

import java.util.function.Consumer;
import java.util.function.Predicate;

public interface InternalFactHandle
    extends
        FactHandle, Cloneable {
    int getId();

    long getRecency();

    Object getObject();

    String getObjectClassName();

    void setObject(Object object);

    void setEqualityKey(EqualityKey key);

    EqualityKey getEqualityKey();

    void setRecency(long recency);

    void invalidate();
    
    boolean isValid();
    
    int getIdentityHashCode();

    int getObjectHashCode();
    
    boolean isDisconnected();
    
    /**
     * Returns true if this FactHandle represents
     * and Event or false if this FactHandle represents
     * a regular Fact
     * 
     * @return
     */
    boolean isEvent();

    boolean isTraitOrTraitable();

    boolean isTraitable();

    boolean isTraiting();

    TraitTypeEnum getTraitType();
    
    RightTuple getFirstRightTuple();

    LeftTuple getFirstLeftTuple();

    WorkingMemoryEntryPoint getEntryPoint();
    void setEntryPoint(WorkingMemoryEntryPoint ep);
    
    InternalFactHandle clone();
    
    String toExternalForm();
    
    void disconnect();

    void addFirstLeftTuple(LeftTuple leftTuple);

    void addLastLeftTuple(LeftTuple leftTuple);

    void removeLeftTuple(LeftTuple leftTuple);

    void clearLeftTuples();

    void clearRightTuples();

    void addFirstRightTuple(RightTuple rightTuple);

    void addLastRightTuple(RightTuple rightTuple);

    void removeRightTuple(RightTuple rightTuple);

    void addTupleInPosition(Tuple tuple);

    boolean isNegated();
    void setNegated(boolean negated);

    <K> K as(Class<K> klass) throws ClassCastException;

    boolean isExpired();
    boolean isPendingRemoveFromStore();

    void forEachRightTuple(Consumer<RightTuple> rightTupleConsumer);
    void forEachLeftTuple(Consumer<LeftTuple> leftTupleConsumer);

    RightTuple findFirstRightTuple(Predicate<RightTuple> rightTuplePredicate);
    LeftTuple findFirstLeftTuple(Predicate<LeftTuple> lefttTuplePredicate);

    void setFirstLeftTuple(LeftTuple firstLeftTuple);

    LinkedTuples detachLinkedTuples();
    LinkedTuples detachLinkedTuplesForPartition(int i);

    LinkedTuples getLinkedTuples();

    interface LinkedTuples {
        LinkedTuples clone();

        void addFirstLeftTuple(LeftTuple leftTuple);
        void addLastLeftTuple(LeftTuple leftTuple);

        void addTupleInPosition(Tuple tuple);

        void removeLeftTuple(LeftTuple leftTuple);

        void addFirstRightTuple(RightTuple rightTuple);
        void addLastRightTuple(RightTuple rightTuple);

        void removeRightTuple(RightTuple rightTuple);

        void clearLeftTuples();
        void clearRightTuples();

        void forEachRightTuple(Consumer<RightTuple> rightTupleConsumer);
        RightTuple findFirstRightTuple(Predicate<RightTuple> rightTuplePredicate);

        void forEachLeftTuple(Consumer<LeftTuple> leftTupleConsumer);
        LeftTuple findFirstLeftTuple(Predicate<LeftTuple> leftTuplePredicate);

        LeftTuple getFirstLeftTuple(int partition);
        void setFirstLeftTuple(LeftTuple firstLeftTuple, int partition);

        default LeftTuple getFirstLeftTuple(RuleBasePartitionId partitionId) {
            return getFirstLeftTuple( partitionId.getParallelEvaluationSlot() );
        }
        default void setFirstLeftTuple(LeftTuple firstLeftTuple, RuleBasePartitionId partitionId) {
            setFirstLeftTuple( firstLeftTuple, partitionId.getParallelEvaluationSlot() );
        }

        RightTuple getFirstRightTuple(int partition);

        default RightTuple getFirstRightTuple(RuleBasePartitionId partitionId) {
            return getFirstRightTuple( partitionId.getParallelEvaluationSlot() );
        }
    }

    default InternalDataSource<?> getDataSource() {
        return null;
    }

    default InternalFactHandle getParentHandle() {
        return null;
    }

    default void setParentHandle(InternalFactHandle parentHandle) {
        throw new UnsupportedOperationException();
    }
}
